<div class="m-t">
	                      <!-- 文章开始 -->
	                      <div id="newsContent" class="markdown-article"><div><h1><a href="#smvc" name="smvc">SMVC</a></h1>
<p>====================</p>
<p><img src="https://img.shields.io/cocoapods/l/TWPhotoPicker.svg" alt="License"><br><img src="https://img.shields.io/badge/platform-java-yellow.svg" alt="Platform"></p>
<blockquote>
  <p><strong>SMVC</strong> 是基于java开发的轻量级MVC框架，框架依赖于spring-core。 </p>
</blockquote>
<p>框架开发目的：该框架原型是为了学习spring-mvc而写的demo，但后来该框架在实际项目中得到了应用，该框架具有如下特点： </p>
<ul>
  <li>框架无入侵，只要注解即可完成路由配置；</li>
  <li>路由配置灵活，业务service即加上注解就是接口，返回值就是json或者页面名字；</li>
  <li>请求值要求json还是form、返回json还是返回页面 只需要注解即可搞定；request中的参数自动注入到接口方法参数中；</li>
  <li>拦截器配置极为简单，只需要简单注解。</li>
  <li>统一的异常处理，代码中再也不需要管任何异常，直接抛出去就好，出错了框架会为你返回错误码。</li>
</ul>
<h2><a href="#installation" name="installation">Installation</a></h2>
<p>如何使用该框架？ 下载代码，其中有使用demo，你可以自由的修改代码，做任何你需要的定制。</p>
<h2><a href="#requirements" name="requirements">Requirements</a></h2>
<ul>
  <li>java 6.0+</li>
</ul>
<h2><a href="#license" name="license">License</a></h2>
<p>SMVC is available under the Apache license, see the LICENSE file for more information.</p>
<h2><a href="#使用指南" name="使用指南">使用指南</a></h2>
<h3>1.接口返回类型：页面或JSON</h3>
<blockquote>
  <p>只需要在接口方法上指定returnType</p>
</blockquote>
<h4>1.1 返回页面(DemoPage.java, <a href="p">测试</a>)</h4>
<pre><code>	@RequestMapping(value = "", returnType = ReturnType.PAGE)
	public String index()
	{
		// 返回index页面
		return "index";
	}
</code></pre>
<h4>1.2 返回JSON(DemoInterface.java, <a href="i/returnData">测试</a>)</h4>
<p>只需要在接口方法上指定returnType</p>
<pre><code>	@RequestMapping(value = "returnData", returnType = ReturnType.JSON)
	public String returnData()
	{
		// 返回数据（框架自动打包为json）
		return "smvc maybe good.";
	}
</code></pre>
<h3>2. 返回数据</h3>
<h4>2.1 对于返回页面，在接口方法上指定增加Map类型参数，接口中增加入Map的值就是返回给页面的值(DemoPage.java, <a href="p/returnValue">测试</a>)</h4>
<pre><code>	@RequestMapping(value = "returnValue", returnType = ReturnType.PAGE)
	public String returnValue(Map&lt;Object, Object&gt; returnMap)
	{
		returnMap.put("returnValue1", 1);
		returnMap.put("returnValue2", 2);
		// 返回页面
		return "returnValue";
	}
</code></pre>
<h4>2.2 对于返回JSON，框架自动对返回值进行包装(DemoInterface.java, <a href="i/returnData">测试</a>)</h4>
<p>接口：</p>
<pre><code>	@RequestMapping(value = "returnData", returnType = ReturnType.JSON)
	public String returnData()
	{
		// 直接抛出异常
		return "smvc maybe good.";
	}
</code></pre>
<p>返回值：</p>
<pre><code>{ "code":0, "data":"smvc maybe good.", "message":"", "returnCode":"" }
</code></pre>
<h3>3.参数自动注入</h3>
<h4>3.1 路由参数自动注入接口参数(DemoPage.java, <a href="p/routeParamInject/dingxiangyong/123">测试</a>)</h4>
<blockquote>
  <p>注意：参数类型须为java基本对象型<br>如下接口，路由中的name和id的值自动注入到接口name和id变量中。 </p>
  <pre><code>	@RequestMapping(value = "routeParamInject/{name}/{id}", returnType = ReturnType.PAGE)
	public String routeParamInject(String name, Integer id, Map&lt;Object, Object&gt; returnMap)
	{
		returnMap.put("name", name);
		returnMap.put("id", id);
		// 返回页面
		return "routeParamInject";
	}
</code></pre>
</blockquote>
<h4>3.2 HTTP参数注入接口参数(java基本对象性)(DemoPage.java, <a href="p/httpParamInject?name=dingxiangyong&id=123">测试</a>)</h4>
<p>接口</p>
<pre><code>	@RequestMapping(value = "httpParamInject", returnType = ReturnType.PAGE)
	public String httpParamInject(String name, Integer id, Map&lt;Object, Object&gt; returnMap)
	{
		returnMap.put("name", name);
		returnMap.put("id", id);
		// 返回页面
		return "httpParamInject";
	}
</code></pre>
<p>url(post和get均支持)</p>
<pre><code>http://localhost:8080/smvc-demo/p/httpParamInject?name=dingxy&amp;id=1234
</code></pre>
<h3>3.3 JSON参数注入接口参数(用户自定义对象性)(DemoPage.java, <a href="p/jsonParamInject?{%22name%22:%22dingxy%22,%22id%22:1234}">测试</a>)</h3>
<p>注解RequestMapping的requestDataType 变量默认为FORMDATA，也就是仅支持HTTP参数方式，如果需要支持JSON转换，需要指定**requestDataType = RequestDataType.JSON**</p>
<p>接口</p>
<pre><code>	@RequestMapping(value = "jsonParamInject", requestDataType = RequestDataType.JSON, returnType = ReturnType.PAGE)
	public String jsonParamInject(HttpParamInjectRequest request, Map&lt;Object, Object&gt; returnMap)
	{
		Assert.notNull(request);
		returnMap.put("name", request.getName());
		returnMap.put("id", request.getId());
		// 返回页面
		return "httpParamInject";
	}
</code></pre>
<p>url(post和get均支持)</p>
<pre><code>http://localhost:8080/smvc-demo/p/jsonParamInject?{"name":"dingxy","id":1234}
</code></pre>
<h3>4.异常处理</h3>
<h4>4.1 JSON接口异常处理(DemoInterface.java, <a href="i/throwException">测试</a>)</h4>
<p>接口一切正常时返回json的code为0，其他异常情况为1。returnCode来自于抛出的BusinessException的errorcode，如果非BusinessException或者未指定errorcode，那么默认返回000001。</p>
<pre><code>	@RequestMapping(value = "throwException", returnType = ReturnType.JSON)
	public void throwException()
	{
		// 直接抛出异常
		throw new BusinessException("101010", "接口抛出异常");
	}
</code></pre>
<p>返回值如下</p>
<pre><code>{ "code":1, "data":"", "message":"接口抛出异常", "returnCode":"101010" }
</code></pre>
<h4>4.2 页面接口异常处理(DemoPage.java, <a href="p/throwException">测试</a>)</h4>
<p>页面接口发生异常均返回HTTP 500状态码，如果配置了errorpage那么会自动走到500对应页面上。</p>
<pre><code>	@RequestMapping(value = "throwException", returnType = ReturnType.JSON)
	public void throwException()
	{
		// 直接抛出异常
		throw new BusinessException("101010", "接口抛出异常");
	}
</code></pre>
<h4>4.3 访问不存在的接口(<a href="p/unknown">测试</a>)</h4>
<p>返回HTTP 404状态吗，如果配置了errorpage那么会自动走到404对应页面上。</p>
<h3>5.业务service即加上注解就是接口，返回值就是json(DemoInterface.java, <a href="i/returnDataObj?name=dingxy&id=1234">测试</a>)</h3>
<p>接口</p>
<pre><code>	@RequestMapping(value = "returnDataObj", returnType = ReturnType.JSON)
	public ReturnDataResponse returnDataObj(String name, Integer id)
	{
		Assert.notNull(name);
		Assert.notNull(id);

		ReturnDataResponse response = new ReturnDataResponse();
		response.setName(name);
		response.setId(id);

		return response;
	}
</code></pre>
<p>其中ReturnDataResponse为</p>
<pre><code>public class ReturnDataResponse
{
	private String name;
	private Integer id;

        // getter and setter
}
</code></pre>
<p>请求URL</p>
<pre><code>http://localhost:8080/smvc-demo/i/returnDataObj?name=dingxy&amp;id=1234
</code></pre>
<p>返回值</p>
<pre><code>{ "code":0, "data":{ "id":1234, "name":"dingxy" }, "message":"", returnCode":"" }
</code></pre>
<h3>6.文件上传支持</h3>
<p>直接将文件input域的名字作为接口方法参数或者请求参数的域。<br>单文件上传((DemoPage.java, <a href="upload_one_file.html">测试</a>))</p>
<pre><code>	@RequestMapping(value = "oneFileUpload", returnType = ReturnType.JSON)
	public String oneFileUpload(MultipartFile file)
</code></pre>
<p>多文件上传(参数为MultipartFile数组, 如：upload_multi_file.html)(DemoPage.java, <a href="upload_multi_file.html">测试</a>)</p>
<pre><code>	@RequestMapping(value = "multiFileUpload", returnType = ReturnType.JSON)
	public String multiFileUpload(MultipartFile[] file)
</code></pre>
<h3>7.拦截器</h3>
<h4>7.1 注解Intercept：作用目标为类和方法，表示该拦截器在该类或该方法对应的接口上工作；(DemoInterceptInterface.java, <a href="i/needLogin">测试</a>)</h4>
<pre><code>	@Intercept(value = { LoginInterceptor.class })
    public class DemoInterceptInterface
</code></pre>
<p>方法上使用Intercept注解，增加ExecuteTimeInterceptor拦截器(DemoInterceptInterface.java, <a href="i/executeTime">测试</a>)<p>
<pre><code>	    @RequestMapping(value = "executeTime", returnType = ReturnType.JSON)
    @Clear(value = { LoginInterceptor.class })
    @Intercept(value = { ExecuteTimeInterceptor.class })
    public void executeTime()
    {
        // 该接口会被ExecuteTimeInterceptor拦截
    }
</code></pre>
<h4>7.2 注解Clear：作用目标方法，表示该拦截器在该方法对应的接口不工作(DemoInterceptInterface.java, <a href="i/noNeedLogin">测试</a>)</h4>
<p>页面接口发生异常均返回HTTP 500状态码，如果配置了errorpage那么会自动走到500对应页面上。</p>
<pre><code>	    @RequestMapping(value = "noNeedLogin", returnType = ReturnType.JSON)
    @Clear(value = { LoginInterceptor.class })
    public void noNeedLogin()
    {
        // 该接口执行不需要登陆
    }
</code></pre>
</div></div>
	                      <!-- 文章结束 -->
	                    </div>